#region Imported Namespaces


using System;
using System.Windows;


#endregion


namespace WtfManager.Framework
{
  ///<summary>
  /// An interface for Wtf Framework Elements
  ///</summary>
  public abstract class FrameworkComponent: DependencyObject
  {
    #region Fields


    private FrameworkComponentState _state;


    #endregion


    #region Properties/Indexers


    /// <summary>
    /// Gets a description of a component.
    /// </summary>
    public abstract string Description
    {
      get;
    }

    public bool IsInitialized
    {
      get
      {
        return _state == FrameworkComponentState.Initialized;
      }
    }


    public bool IsInitializing
    {
      get
      {
        return _state == FrameworkComponentState.Initializing;
      }
    }

    ///<summary>
    /// Returns true, if component was loaded.
    ///</summary>
    public bool IsLoaded
    {
      get
      {
        return _state != FrameworkComponentState.Unloaded;
      }
    }


    /// <summary>
    /// Gets a name of a component.
    /// </summary>
    public abstract string Name
    {
      get;
    }

    ///<summary>
    /// Returns true, if component was initialized.
    ///</summary>
    public FrameworkComponentState State
    {
      get
      {
        return _state;
      }
      internal set
      {
        if (_state == value)
        {
          return;
        }

        _state = value;

        OnStateChnaged();

        if (StateChanged != null)
        {
          StateChanged(this, EventArgs.Empty);
        }
      }
    }


    #endregion


    #region Events


    public event EventHandler StateChanged;


    #endregion


    #region Methods


    protected abstract void OnStateChnaged();


    ///<summary>
    /// Initializes a component.
    ///</summary>
    public void Initialize()
    {
      FrameworkComponentState state;

      try
      {
        state = InitializeComponent();
      }
      catch (Exception e)
      {
        // TODO <RNovitsky, 28.04.2009>: Log this
        State = FrameworkComponentState.Error;
        return;
      }

      if (state != FrameworkComponentState.Initializing && state != FrameworkComponentState.Initialized)
      {
        State = FrameworkComponentState.Error;
      }
      else
      {
        State = state;
      }
    }


    protected abstract FrameworkComponentState InitializeComponent();


    /// <summary>
    /// Loads component.
    /// </summary>
    public void Load()
    {
      FrameworkComponentState state;

      try
      {
        state = LoadComponent();
      }
      catch (Exception e)
      {
        // TODO <RNovitsky, 28.04.2009>: Log this
        State = FrameworkComponentState.Error;
        return;
      }

      if (state != FrameworkComponentState.Loading && state != FrameworkComponentState.Loaded)
      {
        State = FrameworkComponentState.Error;
      }
      else
      {
        State = state;
      }
    }


    protected abstract FrameworkComponentState LoadComponent();


    /// <summary>
    /// Unloads component.
    /// </summary>
    public void Unload()
    {
      try
      {
        OnUnload();
      }
      catch (Exception e)
      {
        // TODO <RNovitsky, 28.04.2009>: Log this
        State = FrameworkComponentState.Error;
        return;
      }

      State = FrameworkComponentState.Unloaded;
    }


    protected abstract void OnUnload();


    public override string ToString()
    {
      return string.Format("[Name: {0}, State: {1}]", Name, State);
    }


    #endregion
  }
}